<?php
// +----------------------------------------------------------------------
// | Bwsaas
// +----------------------------------------------------------------------
// | Copyright (c) 2015~2020 http://www.buwangyun.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Gitee ( https://gitee.com/buwangyun/bwsaas )
// +----------------------------------------------------------------------
// | Author: buwangyun <hnlg666@163.com>
// +----------------------------------------------------------------------
// | Date: 2020-9-28 10:55:00
// +----------------------------------------------------------------------

namespace buwang\util\corn;

use Swoole\Timer;
use think\facade\Log;
use think\swoole\Manager;

/**
 * mn定时任务
 * Class Cron
 * @package buwang\util
 */
class MnCron
{
    protected $manager;
    protected $workerId = 0;
    /**
     * 构造函数
     * @param Manager $manager
     */
    public function __construct(Manager $manager)
    {
        $this->manager = $manager;
    }


    /**
     * 沙盒运行定时任务-即使回调函数抛出异常，也不会导致整个程序崩溃。
     * @param callable $callable
     */
    protected function runInSandbox(callable $callable)
    {
        $this->manager->runWithBarrier([$this->manager, 'runInSandbox'], function () use ($callable) {
            try {
                $callable();
            } catch (\Throwable $e) {
                Log::error($e->getMessage().':'.$e->getFile().':'.$e->getLine());
            }
        });
    }

    /**
     * 添加启动定时任务
     * @param int $mn
     * @param callable $callable
     * @return int|null
     */
    public function corn_tick(int $mn, callable $callable)
    {
        if ($this->workerId === $this->manager->getWorkerId()) {
            return Timer::tick($mn, function () use ($callable) {
                $this->runInSandbox($callable);
            });
        } else {
            return null;
        }
    }


    /**
     * 单次执行定时任务
     * @param int $mn
     * @param callable $callable
     * @return void
     */
    public function corn_after(int $mn, callable $callable)
    {
        Timer::after($mn, function () use ($callable) {
            $this->runInSandbox($callable);
        });
    }

}
